package com.nicefact.mailmonitor.controller;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.nicefact.mailmonitor.core.APP_CONSTANTS;
import com.nicefact.mailmonitor.core.AppException;
import com.nicefact.mailmonitor.entity.AppAdmin;
import com.nicefact.mailmonitor.entity.BlobHistory;
import com.nicefact.mailmonitor.service.AppAdminService;
import com.nicefact.mailmonitor.service.AppFileService;
import com.nicefact.mailmonitor.service.AppUserService;
import com.nicefact.mailmonitor.service.BlobHistoryService;
import com.nicefact.mailmonitor.vo.AppProperties;
import com.nicefact.mailmonitor.workflow.WorkflowInfo;
import com.nicefact.mailmonitor.workflow.entity.Workflow;
import com.nicefact.mailmonitor.workflow.impl.context.AuthorizeContextIOForAllDomainUsersContext;
import com.nicefact.mailmonitor.workflow.impl.context.ReadCSVContext;
import com.nicefact.mailmonitor.workflow.impl.processor.WorkflowStatusType;
import com.nicefact.mailmonitor.workflow.impl.task.ReportGenerationTask;
import com.nicefact.mailmonitor.workflow.service.WorkflowService;

@Controller
public class HomeController {

	@Autowired
	AppProperties appProperties;

	@Autowired
	WorkflowService workflowService;

	@Autowired
	AppUserService appUserService;

	@Autowired
	AppFileService appFileService;
	
	@Autowired
	AppAdminService appAdminService;

	@Autowired
	private BlobHistoryService blobHistoryService;

	@RequestMapping({ "/index.do", "/" })
	public String showHomePage(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();		
		if (user == null) {
			response.sendRedirect(userService.createLoginURL(request
					.getRequestURI()));
			return null;
		} else {
			HttpSession session = request.getSession();
			if (session.getAttribute(APP_CONSTANTS.USER) == null) {
				session.setAttribute(APP_CONSTANTS.USER, user.getEmail());
			}
			if (session.getAttribute(APP_CONSTANTS.IS_ADMIN) == null) {
				Boolean isAdmin = appUserService.isDomainAdmin(user.getEmail());
				session.setAttribute(APP_CONSTANTS.IS_ADMIN, isAdmin);
				if(isAdmin){
					AppAdmin appAdmin=appAdminService.get(user.getEmail());
					if(appAdmin==null){
						appAdmin = new AppAdmin(user.getEmail(), user.getNickname());						
						appAdmin = appAdminService.save(appAdmin);
					}
					session.setAttribute(APP_CONSTANTS.APP_ADMIN, appAdmin);
				}
			}
		}
		return APP_CONSTANTS.INDEX_PAGE;
	}

	String getLoggedInUserEmail(HttpSession session) {
		String email = null;
		if (session.getAttribute(APP_CONSTANTS.USER) == null) {
			session.setAttribute(APP_CONSTANTS.USER, UserServiceFactory
					.getUserService().getCurrentUser().getEmail());
		}
		email = (String) session.getAttribute(APP_CONSTANTS.USER);
		return email;
	}

	@RequestMapping("/logout.do")
	public void doLogout(HttpSession session, HttpServletRequest request,
			HttpServletResponse response) throws AppException {
		session.setAttribute("logoutAction", new Boolean(true));
		UserService userService = UserServiceFactory.getUserService();
		String logoutUrl = userService.createLogoutURL("/index.do");
		session.invalidate();
		try {
			((HttpServletResponse) response).sendRedirect(logoutUrl);

		} catch (IOException ioe) {
			throw new AppException("Unable to logout", ioe);
		}
	}

	@RequestMapping("/getFileList.do")
	@ResponseBody
	public Map<String, Object> getFileList(HttpSession session,
			HttpServletRequest request, HttpServletResponse response) {
		Map<String, Object> modalMap = new HashMap<String, Object>();
		AppAdmin appAdmin = (AppAdmin) session.getAttribute(APP_CONSTANTS.APP_ADMIN);
		List<BlobHistory> blobHistories = blobHistoryService
				.getLastTenUploads(appAdmin.getEmail());
		ArrayList<HashMap<String, Object>> rows = new ArrayList<HashMap<String, Object>>();
		int id = 0;
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd hh:mm a");
		for (BlobHistory blobHistory : blobHistories) {
			HashMap<String, Object> data = new HashMap<String, Object>();
			data.put("id", ++id);
			ArrayList<Object> row = new ArrayList<Object>();
			row.add(blobHistory.getBlobKeyStr());
			row.add(blobHistory.getFileName());
			row.add(blobHistory.getMonth());
			row.add(formatter.format(blobHistory.getCreateDate()));
			row.add(blobHistory.getCreatedBy());
			data.put("cell", row);
			rows.add(data);
		}
		modalMap.put("rows", rows);
		modalMap.put("page", 1);
		modalMap.put("total", 10);

		modalMap.put("records", 10);
		return modalMap;
	}

	@RequestMapping("/syncAllUsers.do")
	@ResponseBody
	public Boolean syncUsers(HttpSession session, HttpServletRequest request,
			HttpServletResponse response) throws AppException {
		createSyncUserWorkflow(getLoggedInUserEmail(session));
		return true;
	}
	

	@RequestMapping("/downloadReport.do")
	public void downloadReport(HttpSession session, HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam("blobKeyStr") String blobKeyStr,
			@RequestParam("fileName") String fileName) throws IOException {
		BlobKey blobKey = new BlobKey(blobKeyStr);
		if (StringUtils.isBlank(fileName)) {
			fileName = "MailStatisticsReport.csv";
		}
		response.setHeader("Content-Disposition", "attachment; filename=\""
				+ fileName + "\"");
		response.setContentType("text/csv;charset=utf-8");
		BlobstoreService blobstoreService = BlobstoreServiceFactory
				.getBlobstoreService();
		;
		blobstoreService.serve(blobKey, response);

		// return appFileService.getBytesFromBlob("Rq8m5P4gioWXVbxevSowXQ");
	}

	@RequestMapping("/generateReport.do")
	public void generateReport(
			HttpSession session,
			HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "fromDate", required = false) String fromDateStr,
			@RequestParam(value = "toDate", required = false) String toDateStr,
			@RequestParam(value = "mailTo", required = false) String emailId)
			throws IOException, AppException {
		String msg = "Report will be available for download shortly. Please revisit this page in about 30 minutes";
		Date fromDate = getDate(fromDateStr);
		Date toDate = getDate(toDateStr);
		BlobstoreService blobstoreService = BlobstoreServiceFactory
				.getBlobstoreService();
		Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request);
		List<BlobKey> reprotBlobs = blobs.get("reportFile");

		if (!ReportGenerationTask.isTaskRunning()) {
			if (reprotBlobs != null && !reprotBlobs.isEmpty()) {
				BlobKey blobKey = reprotBlobs.get(0);
				String adminEmail = getLoggedInUserEmail(session);
				// TODO if mailing change 2nd param to email address of
				// recipient
				triggerReportGenerationTask(adminEmail, adminEmail, fromDate,
						toDate, blobKey);
			} else {
				msg = "<span style='color:red'>Please provide a valid CSV file</span>";
			}
		} else {
			msg = "<span style='color:red'>Previous Task is still running. Please try after some time</span>";
		}
		response.sendRedirect("/index.do?msg=" + msg);
	}

	void triggerReportGenerationTask(String adminEmail, String mailToEmail,
			Date from, Date to, BlobKey blobKey) throws AppException {
		ReadCSVContext context = new ReadCSVContext();
		context.setAdminEmail(adminEmail);
		context.setFromDate(from);
		context.setToDate(to);
		context.setBlobKey(blobKey);
		WorkflowInfo workflowInfo = new WorkflowInfo("ReadCSVTaskProcessor");
		workflowInfo.setIsNewWorkflow(true);

		Workflow workflow = new Workflow();
		workflow.setContext(context);
		workflow.setWorkflowName(workflowInfo.getWorkflowName());
		workflow.setWorkflowInstanceId(workflowInfo.getWorkflowInstance());
		workflow.setWorkflowStatus(WorkflowStatusType.INPROGRESS.toString());
		workflow = workflowService.createWorkflow(workflow);
		context.setWorkflowInfo(workflowInfo);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		workflowService.triggerWorkflow(workflow);
	}

	private Date getDate(String dateStr) {
		Date date = null;
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
		if (!StringUtils.isEmpty(dateStr)) {
			try {
				date = formatter.parse(dateStr);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return date;
	}

	void createSyncUserWorkflow(String email) throws AppException {
		AuthorizeContextIOForAllDomainUsersContext context = new AuthorizeContextIOForAllDomainUsersContext();
		context.setAdminEmail(email);
		WorkflowInfo workflowInfo = new WorkflowInfo(
				"AuthorizeContextIOForAllDomainUsersProcessor");
		workflowInfo.setIsNewWorkflow(true);

		Workflow workflow = new Workflow();
		workflow.setContext(context);
		workflow.setWorkflowName(workflowInfo.getWorkflowName());
		workflow.setWorkflowInstanceId(workflowInfo.getWorkflowInstance());
		workflow.setWorkflowStatus(WorkflowStatusType.INPROGRESS.toString());
		workflow = workflowService.createWorkflow(workflow);
		context.setWorkflowInfo(workflowInfo);
		workflowService.triggerWorkflow(workflow);
	}

}
